/*
 * Copyright (C) 2017 ~ 2019 Deepin Technology Co., Ltd.
 *
 * Author:     zhangbingyi <zhangbingyi@uniontech.com>
 *
 * Maintainer: zhangbingyi <zhangbingyi@uniontech.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include "securitylevelmodel.h"
#include "invokers/invokerfactory.h"
#include "gsettingkey.h"
#include "common.h"

#include <pwd.h>
#include <unistd.h>

SecurityLevelModel::SecurityLevelModel(QObject *parent)
    : QObject(parent)
    , m_systemLevelDBusInter(nullptr)
    , m_gsetting(nullptr)
    , m_accountsDBusInter(nullptr)
    , m_isEnhanceInstall(false)
{
    // 初始化安全中心gsetting配置
    m_gsetting = InvokerFactory::GetInstance().CreateSettings("com.deepin.dde.deepin-defender", QByteArray(), this);

    m_systemLevelDBusInter = InvokerFactory::GetInstance().CreateInvoker("com.deepin.defender.MonitorNetFlow",
                                                                         "/com/deepin/defender/systemlevel",
                                                                         "com.deepin.defender.systemlevel",
                                                                         ConnectType::SYSTEM, this);

    // 连接等保结果返回槽
    m_systemLevelDBusInter->Connect("NotifySystemLevelSettingResult", this, SLOT(getSystemLevelSettingResult(bool, int)));

    struct passwd *pws;
    pws = getpwuid(getuid());
    m_currentUserName = QString(pws->pw_name);

    // 获取等保安装信息
    QDBusMessage msg = DBUS_BLOCK_INVOKE(m_systemLevelDBusInter, "QuerySystemLevelStatus");
    GET_MESSAGE_VALUE(QString, sStatus, msg);
    if (sStatus.isEmpty()) {
        m_isEnhanceInstall = false;
    } else {
        m_isEnhanceInstall = true;
    }

    m_accountsDBusInter = InvokerFactory::GetInstance().CreateInvoker("org.freedesktop.Accounts",
                                                                      "/org/freedesktop/Accounts",
                                                                      "org.freedesktop.Accounts",
                                                                      ConnectType::SYSTEM, this);
}

// 获取当前系统安全等级gsetting
int SecurityLevelModel::getSystemSafeLevel()
{
    return m_gsetting->GetValue(SYSTEM_SAFE_LEVEL).toInt();
}

// 设置等保开启/关闭
void SecurityLevelModel::setSystemLevel(int nType, bool isStatus, bool isDeleteUser, const QString &sSysadmPassword, const QString &sSecadmPassword, const QString &sAudadmPassword)
{
    QDBusMessage msg = DBUS_BLOCK_INVOKE(m_systemLevelDBusInter, "SetSystemSafeLevel", getSystemSafeLevel(), nType, isStatus, isDeleteUser, sSysadmPassword, sSecadmPassword, sAudadmPassword);
}

// 得到等保开启/关闭状态
void SecurityLevelModel::getSystemLevelSettingResult(bool isSuccess, int nType)
{
    Q_EMIT notifySystemLevelChangeFinish(isSuccess, nType);
}

// 设置系统安全等级切换
void SecurityLevelModel::setSystemLevelChange(int nType)
{
    DBUS_BLOCK_INVOKE(m_systemLevelDBusInter, "SetSystemSafeItemType", getSystemSafeLevel(), nType);
}

// 得到当前用户
QString SecurityLevelModel::getCurrentUserName()
{
    return m_currentUserName;
}

// 是否显示高等级
bool SecurityLevelModel::isShowHighLevel()
{
    return m_isEnhanceInstall;
}

bool SecurityLevelModel::getIsWaylandDisplay()
{
    bool isWaylandDisplay = false;
    // 获取系统用户路径
    QVariantList args = DBUS_BLOCK_INVOKE(m_accountsDBusInter, "ListCachedUsers").arguments();
    if (!args.isEmpty()) {
        QVariant var = args.first();
        QDBusArgument ba = var.value<QDBusArgument>();
        QList<QString> sTypeList;
        ba >> sTypeList;
        // 获取每个用户的XSession值，已和控制中心确认 XSession == deepin  就是X11 架构，不是则为wayland
        // 为了防止XSession查到的为空，改为 XSession == wayland 判断
        for (int i = 0; i < sTypeList.count(); i++) {
            DBusInvokerInterface *user;
            if (m_accountInterMap[sTypeList.at(i)]) {
                user = m_accountInterMap[sTypeList.at(i)];
            } else {
                user = InvokerFactory::GetInstance().CreateInvoker("org.freedesktop.Accounts",
                                                                   sTypeList.at(i),
                                                                   "org.freedesktop.Accounts.User",
                                                                   ConnectType::SYSTEM, this);

                m_accountInterMap[sTypeList.at(i)] = user;
            }

            QVariantList argsUser = DBUS_BLOCK_INVOKE(user, DBUS_PROPERTY_INVOKER_NAME, "XSession").arguments();
            if (!args.isEmpty()) {
                QVariant varUser = argsUser.first();
                QDBusVariant dbvFirstUser = varUser.value<QDBusVariant>();
                QVariant vFirstUser = dbvFirstUser.variant();
                QString sModel = vFirstUser.toString();
                if ("Wayland" == sModel) {
                    isWaylandDisplay = true;
                }
            }
        }
    }
    return isWaylandDisplay;
}
